package com.librelato.tela;

import java.io.ByteArrayInputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.servlet.http.HttpSession;

import net.sf.jmimemagic.Magic;
import net.sf.jmimemagic.MagicMatch;

import org.primefaces.context.RequestContext;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;

import com.librelato.bean.ChamadoBean;
import com.librelato.bean.HistoricoBean;
import com.librelato.bean.TipoProblemaBean;
import com.librelato.bean.UsuarioBean;
import com.librelato.negocio.ChamadoServico;
import com.librelato.negocio.HistoricoChamadoServico;
import com.librelato.negocio.TipoProblemaServico;
import com.librelato.negocio.UsuarioServico;
import com.librelato.negocio.interfaces.IServicoGenerico;
import com.librelato.util.Ferramentas;

@ManagedBean
@ViewScoped
public class ChamadoTela extends TelaAbstrata {

	@ManagedProperty(value = "#{usuario}")
	private UsuarioBean usuario;

	private ChamadoServico<ChamadoBean> servico;

	private UsuarioServico<UsuarioBean> usuarioServico;

	private ChamadoBean chamado;

	private SimpleDateFormat dataFormat;

	private SimpleDateFormat dataFormat2;

	private TipoProblemaServico<TipoProblemaBean> tipoProblemaServico;

	private List<TipoProblemaBean> tipoProblemas;

	private TipoProblemaBean tipoProblema;

	private List<String> destinoChamados;

	private byte[] arquivo;

	private List<ChamadoBean> chamadosAberto;

	private List<ChamadoBean> chamadosFinalizados;

	private String historico;

	private boolean disableRating;

	private Long codChamadoAnt;

	private String dataAteFiltro;

	private String dataDeFiltro;

	private String descricaoFiltro;

	private String destinoChamadoFiltro;

	private String statusFiltro;

	private Long tipoChamadoFiltro;

	private List<Long> dadosChamadoUsuario;

	private HistoricoChamadoServico<HistoricoBean> historicoChamadoServico;

	public ChamadoTela() {
		usuario = usuario == null ? (UsuarioBean) ((HttpSession) FacesContext
				.getCurrentInstance().getExternalContext().getSession(false))
				.getAttribute("usuario") : usuario;
		servico = new ChamadoServico<ChamadoBean>();
		usuarioServico = new UsuarioServico<UsuarioBean>();
		tipoProblema = new TipoProblemaBean();
		chamado = new ChamadoBean();
		dataFormat = new SimpleDateFormat("dd/MM/yy HH:mm:ss");
		dataFormat2 = new SimpleDateFormat("dd/MM/yy");
		tipoProblemaServico = new TipoProblemaServico<TipoProblemaBean>();
		tipoProblemas = new ArrayList<TipoProblemaBean>();
		disableRating = true;
		codChamadoAnt = (Long) null;
		dataAteFiltro = dataFormat2.format(new Date());
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		calendar.add(Calendar.DATE, -30);
		dataDeFiltro = dataFormat2.format(calendar.getTime());
		historicoChamadoServico = new HistoricoChamadoServico<HistoricoBean>();
		try {
			destinoChamados = tipoProblemaServico.buscaDestinoChamados(usuario);
			dadosChamadoUsuario = this.servico
					.estatisticaChamadoUsuario(usuario);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void salvar() {
		try {
			FacesMessage msg = null;
			if (tipoProblema.getDestinoChamado().trim().equals("0")) {
				msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, this
						.getServico().getValor("msg_header_erro"), this
						.getServico().getValor("msg_erro_destino"));

			} else if (tipoProblema.getCodigo() == 0) {
				msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, this
						.getServico().getValor("msg_header_erro"), this
						.getServico().getValor("msg_erro_assunto"));
			} else if (chamado.getDescricao() == null
					|| "".equals(chamado.getDescricao().trim())) {
				msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, this
						.getServico().getValor("msg_header_erro"), this
						.getServico().getValor("msg_comentario_erro"));

			} else {

				chamado.setArquivo(arquivo);
				chamado.setUsuario(usuario);
				chamado.setDataEmissao(new Date());
				chamado.setTipoProblema(tipoProblema);
				chamado.setChamadoAnterior(new ChamadoBean(codChamadoAnt));
				chamado = this.servico.salvar(chamado);
				enviaEmail("Novo Chamado");
				chamado = new ChamadoBean();
				tipoProblema = new TipoProblemaBean();
				codChamadoAnt = null;
				arquivo = null;
				msg = new FacesMessage(FacesMessage.SEVERITY_INFO, this
						.getServico().getValor("msg_header_sucesso"), this
						.getServico().getValor("msg_chamado_sucesso"));
			}

			FacesContext.getCurrentInstance().addMessage(null, msg);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void verificaChamadoNaoQualificado() {
		Map<String, String> param = new HashMap<String, String>();
		param.put("IDUSER", usuario.getCodigo());
		try {
			if (servico.buscaChamadosNaoQualificados(param).size() >= 1) {

				RequestContext.getCurrentInstance().execute("dlgChNQua.show()");
			} else {
				RequestContext.getCurrentInstance().execute("dlg12.show()");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void enviaEmail(String assunto) {
		try {
			List<String> destinos = this.usuarioServico.buscaEmails(chamado,
					"Inclui");
			String destino = "";
			for (String dest : destinos) {
				destino += dest + ",";
			}
			Ferramentas.enviaEmail(Ferramentas.criaCorpoEmail(chamado, ""),
					assunto, destino.substring(0, destino.trim().length() - 1),
					"CHAMADO");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public String converteData(Date data) {
		String dataS = "-";
		if (data != null) {
			dataS = dataFormat.format(data);
		}
		return dataS;
	}

	public void buscaChamadosAberto() {
		try {
			this.chamadosAberto = this.servico.buscaChamadosAberto(
					new HashMap<String, String>(), usuario);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void enviaArquivo(FileUploadEvent event) {
		arquivo = event.getFile().getContents();
		FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, this
				.getServico().getValor("msg_header_sucesso"), this.getServico()
				.getValor("msg_upload")
				+ "("
				+ event.getFile().getFileName()
				+ ")");
		FacesContext.getCurrentInstance().addMessage(null, msg);
	}

	public void buscaTipoProblemas(ValueChangeEvent event) {

		try {
			tipoProblemas = tipoProblemaServico.buscaTipos(event.getNewValue()
					.toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void preencheHistorico(ChamadoBean chamado) {
		this.historico = "";
		for (int i = 0; i < chamado.getHistoricos().size(); i++) {
			this.historico += Ferramentas.formataData(chamado.getHistoricos()
					.get(i).getDataEmissao().getTime(), "dd/MM/yy HH:mm:ss")
					+ "("
					+ chamado.getHistoricos().get(i).getProgresso()
					+ "%) - "
					+ chamado.getHistoricos().get(i).getDescricao()
					+ "<br/>";
		}

	}

	public void atualizaRating(ValueChangeEvent event) {
		if (event.getNewValue().equals(servico.getValor("label_satisfeito"))) {
			disableRating = false;
		} else {
			disableRating = true;
		}

	}

	public void salvaQualificacao() {
		FacesMessage msg = null;
		boolean bPermite = false;
		if (!disableRating) {
			if (chamado.getQualificacao().trim().equals("0")) {
				msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, this
						.getServico().getValor("msg_header_erro"), this
						.getServico().getValor("msg_sem_satisfacao"));
			} else if (chamado.getNotaChamado() == 0) {
				msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, this
						.getServico().getValor("msg_header_erro"), this
						.getServico().getValor("msg_sem_qualificacao"));
			} else if (chamado.getNotaChamado() <= 2
					&& chamado.getObsQualifica().trim().equals("")) {
				msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, this
						.getServico().getValor("msg_header_erro"), this
						.getServico().getValor("msg_observa_erro"));
			} else {
				bPermite = true;
			}
		} else {
			if (chamado.getQualificacao().trim().equals("0")) {
				msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, this
						.getServico().getValor("msg_header_erro"), this
						.getServico().getValor("msg_sem_satisfacao"));
			} else {
				bPermite = true;
			}
		}

		if (bPermite) {
			try {
				chamado.setDataEncerrado(new Date());
				if (chamado.getQualificacao().equals("Satisfeito")) {
					this.servico.insereQualificacao(chamado);
					chamado = new ChamadoBean();
				} else {
					this.servico.insereQualificacaoInsatisfeito(chamado);
					Map<String, String> param = null;
					param = new HashMap<String, String>();
					param.put("IDCHAMADO", chamado.getCodigo() + "");
					String comentario = organizaHistoricos(this.historicoChamadoServico
							.buscaHistoricos(param));
					Ferramentas.enviaEmail(Ferramentas
							.criaCorpoEmailInsatisfeitoParaGerencia(chamado,
									comentario), "Chamado Insatisfeito.",
							"james@librelato.com.br",
							// "jonathan.benedet@librelato.com.br",
							"CHAMADO");
					codChamadoAnt = chamado.getCodigo();
					chamado = new ChamadoBean();
					RequestContext.getCurrentInstance()
							.execute("dlg12.show();");
				}

				msg = new FacesMessage(FacesMessage.SEVERITY_INFO, this
						.getServico().getValor("msg_header_sucesso"), this
						.getServico().getValor("msg_qualifica_sucesso"));

				buscaChamadosAberto();

			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		FacesContext.getCurrentInstance().addMessage(null, msg);
	}

	private String organizaHistoricos(List<HistoricoBean> historicos) {
		StringBuilder sb = new StringBuilder();
		for (HistoricoBean hist : historicos) {
			sb.append("<br/>");
			sb.append(Ferramentas.formataData(hist.getDataEmissao().getTime(),
					"dd/MM/yy hh:mm:ss"));
			sb.append("(" + hist.getProgresso() + "%)");
			sb.append(" - " + hist.getDescricao());
		}

		return sb.toString();
	}

	public StreamedContent downloadArquivo(ChamadoBean chamado) {

		MagicMatch match;
		String mimeType = "";
		try {

			match = Magic.getMagicMatch(chamado.getArquivo());
			mimeType = match.getMimeType();

		} catch (Exception e) {
			mimeType = "application/zip";
		}
		StreamedContent file = new DefaultStreamedContent(
				new ByteArrayInputStream(chamado.getArquivo()), mimeType,
				"Anexo");

		return file;
	}

	public void filtraFinalizados() {
		Map<String, String> param = new HashMap<String, String>();
		if (this.descricaoFiltro != null
				&& !"".equals(this.descricaoFiltro.trim())) {
			param.put("DESCRICAO", this.descricaoFiltro.trim());
		}
		if (this.dataDeFiltro != null && !"".equals(this.dataDeFiltro.trim())) {
			param.put("DATADE", this.dataDeFiltro.trim());
		}
		if (this.dataAteFiltro != null && !"".equals(this.dataAteFiltro.trim())) {
			param.put("DATAATE", dataAteFiltro.trim());
		}
		if (this.destinoChamadoFiltro != null
				&& !"0".equals(this.destinoChamadoFiltro)) {
			param.put("DESTINO", this.destinoChamadoFiltro.trim());
		}
		if (this.tipoChamadoFiltro.toString() != null
				&& !"0".equals(this.tipoChamadoFiltro.toString())) {
			param.put("ASSUNTO", this.tipoChamadoFiltro.toString().trim());
		}

		try {
			this.chamadosFinalizados = this.servico.buscaChamadosFinalizado(
					param, usuario);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void filtraAbertos() {

		Map<String, String> param = new HashMap<String, String>();
		if (this.destinoChamadoFiltro != null
				&& !"0".equals(this.destinoChamadoFiltro)) {
			param.put("DESTINO", this.destinoChamadoFiltro.trim());
		}
		if (this.statusFiltro != null && !"0".equals(this.statusFiltro)) {
			param.put("STATUS", this.statusFiltro.trim());
		}

		try {
			this.chamadosAberto = this.servico.buscaChamadosAberto(param,
					usuario);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void preencheGrafico() {
		try {
			dadosChamadoUsuario = this.servico
					.estatisticaChamadoUsuario(usuario);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void excluiChamado() {
		FacesMessage msg = null;
		try {
			this.servico.excluir(chamado);
			buscaChamadosAberto();
			RequestContext.getCurrentInstance()
					.execute("excluiChamado.hide();");
			msg = new FacesMessage(FacesMessage.SEVERITY_INFO, this
					.getServico().getValor("msg_header_sucesso"), this
					.getServico().getValor("solicita_exclusao_sucesso")
					+ "(Chamado Nº " + chamado.getCodigo() + ")");

		} catch (Exception e) {
			e.printStackTrace();
			msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, this
					.getServico().getValor("msg_header_erro"), this
					.getServico().getValor("solicita_exclusao_erro"));
		}
		FacesContext.getCurrentInstance().addMessage(null, msg);

	}

	public void editaChamado() {
		FacesMessage msg = null;
		try {
			chamado.setArquivo(arquivo);
			this.servico.editar(chamado);
			enviaEmail("Chamado Alterado");
			buscaChamadosAberto();
			msg = new FacesMessage(FacesMessage.SEVERITY_INFO, this
					.getServico().getValor("msg_header_sucesso"), this
					.getServico().getValor("solicita_alteracao_sucesso")
					+ "(Chamado Nº " + chamado.getCodigo() + ")");

		} catch (Exception e) {
			e.printStackTrace();
			msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, this
					.getServico().getValor("msg_header_erro"), this
					.getServico().getValor("solicita_alteracao_erro"));
		}
		FacesContext.getCurrentInstance().addMessage(null, msg);
	}

	public String pintaLinha(ChamadoBean chamado) {
		String classe = "";
		String status = chamado.getStatus();
		if (status.trim().equals("Negado")) {
			classe = "LinhaNega";
		}
		if (status.trim().equals("Aguardando Aprovação")) {
			classe = "LinhaBloq";
		}
		if (status.trim().equals("Em Andamento")) {
			if (chamado.getHistoricos().get(chamado.getHistoricos().size() - 1)
					.getProgresso() == 100) {
				classe = "LinhaComp";
			} else {
				classe = "LinhaAnda";
			}
		}
		if (status.trim().equals("Aberto")) {
			classe = "LinhaApro";
		}

		return classe;
	}

	public void atualizaGraficos() {
		try {
			destinoChamados = tipoProblemaServico.buscaDestinoChamados(usuario);
			dadosChamadoUsuario = this.servico
					.estatisticaChamadoUsuario(usuario);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@SuppressWarnings("rawtypes")
	@Override
	protected IServicoGenerico getServico() {
		return this.servico;
	}

	public ChamadoBean getChamado() {
		return chamado;
	}

	public void setChamado(ChamadoBean chamado) {
		this.chamado = chamado;
	}

	public void setServico(ChamadoServico<ChamadoBean> servico) {
		this.servico = servico;
	}

	public UsuarioBean getUsuario() {
		return usuario;
	}

	public void setUsuario(UsuarioBean usuario) {
		this.usuario = usuario;
	}

	public SimpleDateFormat getDataFormat() {
		return dataFormat;
	}

	public void setDataFormat(SimpleDateFormat dataFormat) {
		this.dataFormat = dataFormat;
	}

	public TipoProblemaServico<TipoProblemaBean> getTipoProblemaServico() {
		return tipoProblemaServico;
	}

	public void setTipoProblemaServico(
			TipoProblemaServico<TipoProblemaBean> tipoProblemaServico) {
		this.tipoProblemaServico = tipoProblemaServico;
	}

	public List<TipoProblemaBean> getTipoProblemas() {
		return tipoProblemas;
	}

	public void setTipoProblemas(List<TipoProblemaBean> tipoProblemas) {
		this.tipoProblemas = tipoProblemas;
	}

	public byte[] getArquivo() {
		return arquivo;
	}

	public void setArquivo(byte[] arquivo) {
		this.arquivo = arquivo;
	}

	public List<String> getDestinoChamados() {
		return destinoChamados;
	}

	public void setDestinoChamados(List<String> destinoChamados) {
		this.destinoChamados = destinoChamados;
	}

	public TipoProblemaBean getTipoProblema() {
		return tipoProblema;
	}

	public void setTipoProblema(TipoProblemaBean tipoProblema) {
		this.tipoProblema = tipoProblema;
	}

	public List<ChamadoBean> getChamadosAberto() {
		return chamadosAberto;
	}

	public void setChamadosAberto(List<ChamadoBean> chamadosAberto) {
		this.chamadosAberto = chamadosAberto;
	}

	public String getHistorico() {
		return historico;
	}

	public void setHistorico(String historico) {
		this.historico = historico;
	}

	public boolean isDisableRating() {
		return disableRating;
	}

	public void setDisableRating(boolean disableRating) {
		this.disableRating = disableRating;
	}

	public Long getCodChamadoAnt() {
		return codChamadoAnt;
	}

	public void setCodChamadoAnt(Long codChamadoAnt) {
		this.codChamadoAnt = codChamadoAnt;
	}

	public SimpleDateFormat getDataFormat2() {
		return dataFormat2;
	}

	public void setDataFormat2(SimpleDateFormat dataFormat2) {
		this.dataFormat2 = dataFormat2;
	}

	public String getDataAteFiltro() {
		return dataAteFiltro;
	}

	public void setDataAteFiltro(String dataAteFiltro) {
		this.dataAteFiltro = dataAteFiltro;
	}

	public String getDataDeFiltro() {
		return dataDeFiltro;
	}

	public void setDataDeFiltro(String dataDeFiltro) {
		this.dataDeFiltro = dataDeFiltro;
	}

	public String getDescricaoFiltro() {
		return descricaoFiltro;
	}

	public void setDescricaoFiltro(String descricaoFiltro) {
		this.descricaoFiltro = descricaoFiltro;
	}

	public List<ChamadoBean> getChamadosFinalizados() {
		return chamadosFinalizados;
	}

	public void setChamadosFinalizados(List<ChamadoBean> chamadosFinalizados) {
		this.chamadosFinalizados = chamadosFinalizados;
	}

	public String getDestinoChamadoFiltro() {
		return destinoChamadoFiltro;
	}

	public void setDestinoChamadoFiltro(String destinoChamadoFiltro) {
		this.destinoChamadoFiltro = destinoChamadoFiltro;
	}

	public Long getTipoChamadoFiltro() {
		return tipoChamadoFiltro;
	}

	public void setTipoChamadoFiltro(Long tipoChamadoFiltro) {
		this.tipoChamadoFiltro = tipoChamadoFiltro;
	}

	public List<Long> getDadosChamadoUsuario() {
		return dadosChamadoUsuario;
	}

	public void setDadosChamadoUsuario(List<Long> dadosChamadoUsuario) {
		this.dadosChamadoUsuario = dadosChamadoUsuario;
	}

	public String getStatusFiltro() {
		return statusFiltro;
	}

	public void setStatusFiltro(String statusFiltro) {
		this.statusFiltro = statusFiltro;
	}

}
